home *** CD-ROM | disk | FTP | other *** search
-
- /* @(#)main.c 1.5 92/04/16
- *
- * Main routine and declarations used by the popi program.
- *
- * Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
- * This version is based on the code in his Prentice Hall book,
- * "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
- * which is copyright (c) 1988 by Bell Telephone Laboratories, Inc.
- *
- * Permission is given to distribute these extensions, as long as these
- * introductory messages are not removed, and no monies are exchanged.
- *
- * No responsibility is taken for any errors or inaccuracies inherent
- * either to the comments or the code of this program, but if reported
- * (see README file) then an attempt will be made to fix them.
- */
-
-
- #include <stdio.h>
- #include <setjmp.h>
- #include <ctype.h>
- #include "popi.h"
- #include "expr.h"
- #include "patchlevel.h"
-
- /* Prototypes for local functions */
-
- static void do_parse P((FILE *)) ;
- static void doit P((Tree *)) ;
- static void get_options P((int, char **[])) ;
- static void Usage P((int)) ;
- int main P((int, char **)) ;
-
- struct SRC Images[MAXIMG] ; /* Array of images. */
- struct SRC *CurOld ; /* Pointer to "old" image */
- struct SRC *CurNew ; /* Pointer to "new" image */
-
- pixel_t *ntsc = NULL ; /* NTSC luma line. */
- pixel_t Zmax = DEF_ZSIZE - 1 ; /* Max brightness level */
-
- FILE *Debug = NULL ; /* Debugging output stream */
- FILE *InputStream = (FILE *) 0 ;
- FILE *LogStr = NULL ; /* Logging output stream */
-
- /* One level of character pushback on stdin to avoid disp_ungetc() */
-
- char SaveChar = '\0' ;
-
- char ErrBuf[256] ;
- char lastfname[MAXPATHLEN] ; /* Last filename parsed. */
- char lastimage[MAXPATHLEN] ; /* Last image name parsed. */
- char *ProgName ; /* Program name (for err messages) */
- char *LogFile = "popi.log" ; /* Name of log file */
- char geometry[MAXLINE] ; /* X11 geometry information. */
- char x11_display[MAXLINE] ; /* X11 display information. */
-
- enum disp_type dtype = IS_COLOR ; /* Display in (color/gray/mono). */
- enum rng_type rng_policy = CUT ; /* Range error handling. */
-
- int noerr = TRUE ;
- int BOXW ; /* Text box width */
- int TXsize ; /* Total width */
- int TYsize ; /* Total height */
- int Xsize = DEF_X ; /* Image width */
- int Ysize = DEF_Y ; /* Image height */
- int Zsize = DEF_ZSIZE ; /* No. brightness levels */
- int Xoffset = 0 ; /* x offset from corner of screen */
- int Yoffset = 0 ; /* y offset from corner of screen */
- int OverlayFlag = FALSE ; /* don't clear screen if true */
- int RangeCheck = 1 ;
- int disp_active = 1 ; /* So we can turn off the display */
- int CharPos = 0 ; /* Current character position on input line */
- int HaveToken = 0 ; /* Set when one (or more) tokens parsed. */
- int OldPos = 0 ; /* Previous character position on input line */
- int TokPos = 0 ; /* Position of beginning of current token */
- int colors = 1 ; /* RGB color mode (default off) */
- int rev_video = 0 ; /* Set if monochrome reverse video. */
- int signed_io = 0 ; /* Signed I/O mode (default off) */
- int Truncate = 0 ; /* Truncate assignments instead of wrapping. */
- int Verbose = 0 ; /* Be chatty */
- int iconic = 0 ; /* Set if the window is in an iconic state. */
- int oldfmt = 0 ; /* Set to save images in old format. */
- int prs = 0 ;
- int tcache = 0 ; /* Set to read/write cached trig info. */
- int saw_eof = 0 ;
- int scr_depth = 1 ; /* Screen depth (where appropriate). */
- int col_used = 0 ; /* colors used in current computation. */
-
- parse_t parsed[MAXTOKENS] ;
-
- Tree *tree ;
-
- static jmp_buf jb ;
-
- #if SEQPAR
- int ncpus = 1 ; /* Default is single-tasking */
- #endif /* SEQPAR */
-
- static char *UsageMsg[] = {
- "\nvalid options:",
- " -a[+-] turn auto-display on (off)",
- " -C display in color",
- " -D[file] enable debugging trace (default stderr)",
- " -d disp specify X11 display",
- " -G display in grayscale",
- " -g geom specify X11 geometry",
- " -i start window iconically",
- " -l[file] log all commands (default ./popi.log)",
- " -M display in monochrome",
- " -o save images to disk in old popi format",
- " -p# specify number of CPUs (if available)",
- " -r[+-] turn range checking on (off)",
- " -s[+-] turn signed I/O mode on (off)",
- " -t[+-] turn trig caching mode on (off)",
- " -V print version number",
- " -v[+-] turn verbose mode on (off)",
- " -xWidth specify initial image width (in pixels)",
- " -yHeight specify initial image height (in scanlines)",
- " -zDepth specify image depth (in levels)",
- (char *) 0
- } ;
-
-
- void
- PrStrs(msg)
- char *msg[] ;
- {
- char **p ;
-
- for (p = msg; *p; ++p) FPRINTF(stderr, "%s\n", *p) ;
- }
-
-
- static void
- Usage(status)
- int status ;
- {
- FPRINTF(stderr, "Usage: %s [options] [image-files]\n", ProgName) ;
- PrStrs(UsageMsg) ;
-
- /* Also need a driver-specific usage message appended. */
-
- exit(status) ;
- }
-
-
- void
- version()
- {
- #if defined(ISTACK)
- FPRINTF(stderr, "%s: (integer) version 3.2.%1d\n",
- ProgName, PATCHLEVEL) ;
- #else
- FPRINTF(stderr, "%s: (floating point) version 3.2.%1d\n",
- ProgName, PATCHLEVEL) ;
- #endif /*ISTACK*/
- }
-
-
- static void
- get_options(argc, argvp) /* Read command line options. */
- int argc ;
- char **argvp[] ;
- {
- extern int yydebug ;
- char **argv ;
- char **new_argv ;
- char **nav ;
-
- argv = *argvp ;
- new_argv = (char **)
- LINT_CAST(Emalloc((unsigned) ((argc + 1) * sizeof (char *)))) ;
- nav = new_argv ;
- for (ProgName = *nav++ = *argv++; *argv && **argv == '-'; ++argv)
- {
- bool ArgRecognised ;
-
- ArgRecognised = TRUE ;
- switch (*++*argv)
- {
- case 'a' : if (*++*argv == '-') /* Auto-display */
- disp_active = 0 ;
- else
- disp_active = 1 ;
- break ;
-
- case 'C' : dtype = IS_COLOR ; /* Display in color. */
- break ;
-
- case 'D' : if (*++*argv)
- {
- if ((Debug = fopen(*argv, "w")) == NULL)
- {
- SPRINTF(ErrBuf,
- "Can't open debug file '%s' - using stderr",
- *argv) ;
- error(ERR_SYS) ;
- Debug = stderr ;
- }
- }
- else Debug = stderr ;
- setbuf(Debug, (char *) NULL) ; /**/
- yydebug = 1 ;
- break ;
-
- case 'd' : ++argv ; /* X11 display information. */
- if (*argv == NULL)
- Usage(0) ; /* Print usage message */
- /*NOTREACHED*/
- STRCPY(x11_display, *argv) ;
- break ;
-
- case 'G' : dtype = IS_GRAY ; /* Display in grayscale. */
- break ;
-
- case 'g' : ++argv ; /* X11 geometry information. */
- if (*argv == NULL)
- Usage(0) ; /* Print usage message */
- /*NOTREACHED*/
- STRCPY(geometry, *argv) ;
- break ;
-
- case 'i' : iconic = 1 ; /* Start window iconically. */
- break ;
-
- case 'l' : if (*++*argv) /* Log all commands */
- LogFile = *argv ;
- OpenLog(&LogStr) ;
- break ;
-
- case 'M' : dtype = IS_MONO ; /* Display in monochrome. */
- break ;
-
- case 'o' : oldfmt = 1 ; /* Save images in old format. */
- break ;
-
- case 'p' : /* No. cpus to use in parallel */
-
- /* Still recognise the option on other machines,
- * so scripts can use this option portably.
- */
-
- #if SEQPAR
- if (*++*argv)
- {
- ncpus = atoi(*argv) ;
- if (ncpus >= cpus_online()) ncpus = cpus_online() - 1 ;
- if (ncpus < 0) ncpus = 0 ;
- }
- else ncpus = cpus_online() - 1 ;
- #endif /* SEQPAR */
-
- break ;
-
- case 'r' : if (*++*argv == '-') /* Range checking */
- RangeCheck = 0 ;
- else
- RangeCheck = 1 ;
- break ;
-
- case 's' : if (*++*argv == '-') /* Signed I/O mode */
- signed_io = 0 ;
- else
- signed_io = 1 ;
- break ;
-
- case 't' : if (*++*argv == '-') /* Trig caching mode */
- tcache = 0 ;
- else
- tcache = 1 ;
- break ;
-
- case 'V' : version() ; /* Print version number. */
- exit(0) ;
- /*NOTREACHED*/
-
- case 'v' : if (*++*argv == '-') /* Verbose */
- Verbose = 0 ;
- else
- ++Verbose ;
- break ;
-
- case 'x' : Xsize = atoi(++*argv) ;
- break ;
-
- case 'y' : Ysize = atoi(++*argv) ;
- break ;
-
- case 'z' : Zsize = atoi(++*argv) ;
- Zmax = (pixel_t) (Zsize - 1) ;
- break ;
-
- case 'X' : Xoffset = atoi(++*argv) ;
- break ;
-
- case 'Y' : Yoffset = atoi(++*argv) ;
- break ;
-
- case 'O' : OverlayFlag = TRUE ;
- break ;
-
- case '?' : Usage(0) ; /* Print usage message */
- /*NOTREACHED*/
-
- /* Note: no error on default because drivers may interpret other options.
- * It's up to them to give an error message if they can.
- */
-
- default : ArgRecognised = FALSE ;
- }
-
- if (!ArgRecognised) *nav++ = *argv ;
- }
- *nav = (char *) 0 ;
-
- CurOld = &Images[0] ; /* Create initial "old" image. */
- CurOld->pix = ImgAlloc(Xsize, Ysize, colors) ;
- CurOld->str = Emalloc((unsigned int) (strlen("old")+1)) ;
- STRCPY(CurOld->str, "old") ;
- CurOld->width = Xsize ;
- CurOld->height = Ysize ;
- CurOld->ncolors = colors ;
- CurOld->Xalloc = Xsize ;
-
- CurNew = &Images[1] ; /* Create initial "new" image. */
- CurNew->pix = ImgAlloc(Xsize, Ysize, colors) ;
- CurNew->str = Emalloc((unsigned int) (strlen("new")+1)) ;
- STRCPY(CurNew->str, "new") ;
- CurNew->width = Xsize ;
- CurNew->height = Ysize ;
- CurNew->ncolors = colors ;
- CurNew->Xalloc = Xsize ;
-
- for (; *argv; ++argv) getpix(*argv, (char *) 0, FALSE) ;
-
- if (colors == 3)
- ntsc = (pixel_t *) Emalloc((unsigned) Xsize * sizeof(pixel_t)) ;
- }
-
-
- /* We deliberately don't exit on error here.
- * The user may have some picture that has taken ages to develop.
- * If we run out of memory, they have a chance to save the image and
- * exit themselves, which they should do as soon as possible.
- */
-
- char *
- Emalloc(n)
- unsigned int n ;
- {
- char *try ;
- static unsigned long TotalAllocated = 0L ;
-
- if ((try = malloc(n)) == NULL)
- {
- SPRINTF(ErrBuf, "Allocate %u bytes failed (total malloc=%ld",
- n, TotalAllocated) ;
- error(ERR_SYS) ;
- }
- CLEARMEM(try, (int) n) ;
- TotalAllocated += n ;
- return(try) ;
- }
-
-
- void
- Quit()
- {
- disp_finish() ;
- exit(0) ;
- }
-
-
- main(argc, argv)
- int argc ;
- char **argv ;
- {
- get_options(argc, &argv) ; /* read the command line options. */
- TXsize = Xsize ;
- if (TXsize < TWIDTH) TXsize = TWIDTH ;
- TYsize = Ysize+100 ;
- BOXW = TXsize-50 ;
-
- disp_init(argc, argv) ;
-
- #if SEQPAR
- m_set_procs(ncpus) ;
- #endif /* SEQPAR */
-
- setjmp(jb) ;
- do_parse((FILE *) 0) ;
- Quit() ;
-
- return 0 ; /* Shut up warning messages from some compilers */
- /*NOTREACHED*/
- }
-
-
- static void
- do_parse(istr)
- FILE *istr ;
- {
- FILE *SaveInput ; /* Saved previous input stream. */
-
- /* Save and then reset current input stream. */
-
- SaveInput = InputStream ;
- InputStream = istr ;
-
- for (;;)
- {
- DEBUG((Debug, "do_parse() - top of loop\n")) ;
- noerr = TRUE ;
-
- /* Display popi prompt and clear input line. Returns length of popi prompt. */
-
- CharPos = (istr) ? 0 : disp_prompt() ;
- HaveToken = 0 ;
-
- if (LogStr)
- {
- FPRINTF(LogStr, "-> ") ;
- FFLUSH(LogStr) ;
- }
-
- yyparse() ;
- if (saw_eof) break ;
- col_used = 0 ;
- if (noerr && tree != NULL) doit(tree) ;
- afree() ;
- }
-
- /* Restore saved previous input stream. */
-
- InputStream = SaveInput ;
- }
-
-
- static void
- doit(t)
- Tree *t ;
- {
- switch (t->t)
- {
- case T_Color : setcolor() ;
- break ;
- case T_Comb : combine(t) ;
- break ;
- case T_Debug : debug(t) ;
- break ;
- case T_Display : displayimg(t) ;
- break ;
- case T_Explo : explode(t) ;
- break ;
- case T_Free : freeimg(t) ;
- break ;
- case T_Genep : genepson(t) ;
- break ;
- case T_Genps : genps(t) ;
- break ;
- case T_Get : getputrgb(t, TRUE) ;
- break ;
- case T_Gray : setgray() ;
- break ;
- case T_Help : help() ;
- break ;
- case T_List : showfiles() ;
- break ;
- case T_Logfile : dolog(t) ;
- break ;
- case T_Luma : luma(t) ;
- break ;
- case T_Matte : matte(t) ;
- break ;
- case T_Melt : melt(t) ;
- break ;
- case T_Mono : setmono() ;
- break ;
- case T_Ofmt : ofmt(t) ;
- break ;
- case T_Oil : oil(t) ;
- break ;
- case T_Put : getputrgb(t, FALSE) ;
- break ;
- case T_Quit : Quit() ;
- break ;
- case T_Range : dorange(t) ;
- break ;
- case T_Read : readimg(t) ;
- break ;
- case T_Shear : shear(t) ;
- break ;
- case T_Signed : dosigned(t) ;
- break ;
- case T_Size : dosize(t) ;
- break ;
- case T_Slice : slice(t) ;
- break ;
- case T_Store : stopict(t, -1, "") ;
- break ;
- case T_Tile : tile(t) ;
- break ;
- case T_Trunc : imtrunc(t) ;
- break ;
- case T_Undo : undo() ;
- break ;
- case T_Verbose : verbose(t) ;
- break ;
- case T_Ver : version() ;
- break ;
- case T_Write : writeimg(t) ;
- break ;
- default : compile(t) ;
- }
- }
-
-
- void
- error(errtype)
- int errtype ;
- {
- DEBUG((Debug, "error: type %d, pos %d msg '%s'\n",
- errtype, TokPos, ErrBuf)) ;
- if (!noerr) return ; /* Already printed a message */
- disp_error(errtype, TokPos) ;
- noerr = FALSE ; /* An error has occurred */
-
- if (LogStr) FPRINTF(LogStr, "Error: %s\n", ErrBuf) ;
- }
-
-
- void
- run_error(errtype)
- int errtype ;
- {
- DEBUG((Debug, "Run error: type %d, pos %d msg '%s'\n",
- errtype, TokPos, ErrBuf)) ;
- disp_error(errtype, TokPos) ;
- if (LogStr) FPRINTF(LogStr, "Run error: %s\n", ErrBuf) ;
- longjmp(jb, 1) ;
- }
-
-
- int
- getImageNo(name)
- char *name ;
- {
- int i ;
-
- for (i = 0; i < nimages; i++)
- if (strcmp(Images[i].str, name) == 0) return(i) ;
- return(-1) ;
- }
-